/*******************************************************************************
 * Copyright (c) 2004, 2005 Elias Volanakis and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Elias Volanakis - initial API and implementation
 *******************************************************************************/
package edu.ccut.saturn.studio.logic;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;

import org.eclipse.core.internal.runtime.InternalPlatform;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.net.URI;
import edu.ccut.saturn.studio.core.exception.XMLException;
import edu.ccut.saturn.studio.core.util.xml.SaturnW3CUtil;

/**
 * The plugin class (singleton).
 * <p>
 * This instance can be shared between all extensions in the plugin. Information
 * shared between extensions can be persisted by using the PreferenceStore.
 * </p>
 * 
 * @see org.eclipse.ui.plugin.AbstractUIPlugin#getPreferenceStore()
 * @author Elias Volanakis
 */
public class ShapesPlugin extends AbstractUIPlugin { // eclipse
	// 插件实例化类

	/** Single plugin instance. */
	private static ShapesPlugin singleton;

	private static List<InputStream> baseComponents;

	private Map<String, Document> map;

	/**
	 * Returns the shared plugin instance.
	 */
	public static ShapesPlugin getDefault() {
		return singleton;
	}

	/**
	 * The constructor.
	 */
	public ShapesPlugin() {
		if (singleton == null) {
			singleton = this;
		}
	}

	@Override
	public void start(BundleContext context) throws Exception {
		getBaseComponentsInputstreams();
		super.start(context);
	}

	public static Map<String, Document> getDocumentsForBaseComponents() {
		List<Document> documents = new ArrayList<Document>();
		Map<String, Document> map = new HashMap<String, Document>();
		List<InputStream> list = baseComponents;
		for (int i = 0; i < list.size(); i++) {
			InputStream inputStream = list.get(i);
//			Document document = ParseDocument.getDocument(inputStream);
			Document document = null;
			try {
				document = SaturnW3CUtil.getDocument(inputStream);
			} catch (XMLException e) {
				e.printStackTrace();
			}
			documents.add(document);
		}
		for (Document document : documents) {
//			String keyentry = ImplInSaturnNode.getSaturnNodeKeyInDocument(
//					document, "component", "name");
			String keyentry = getSaturnNodeKeyInDocument(
			document, "component", "name");
			map.put(keyentry, document);
		}
		return map;
	}

	public void getBaseComponentsInputstreams() {

		map = new HashMap<String, Document>();

		baseComponents = new ArrayList<InputStream>();

		URL installedIn = InternalPlatform.getDefault().getInstallURL();

		String eclipse = installedIn.getPath() + "plugins";

		File pluginsfile = new File(eclipse);

		String[] pluginsJarfiles = this.getFilePathsFromClasspath(
				pluginsfile.getAbsolutePath().toString(), "jar");
		for (int i = 0; i < pluginsJarfiles.length; i++) {
			if (pluginsJarfiles[i].contains("edu.ccut.saturn.basecomponent")) {
				JarFile jarFile;
				File jar = new File(pluginsJarfiles[i]);
				try {
					jarFile = new JarFile(jar);
					Enumeration<?> jarEntries = jarFile.entries();
					while (jarEntries.hasMoreElements()) {
						ZipEntry ze = (ZipEntry) jarEntries.nextElement();
						if (ze.getName().endsWith("component")&& (ze.getName().contains("databaseComponent")||ze.getName().contains("dataOperationComponent"))){

							InputStream zestresam = null;
							try {
								zestresam = jarFile.getInputStream(ze);

								Document document = null;
								try {
									document = SaturnW3CUtil
											.getDocument(zestresam);
								} catch (XMLException e) {
									e.printStackTrace();
								}
//								String keyentry = ImplInSaturnNode
//										.getSaturnNodeKeyInDocument(document,
//												"component", "key");
								String keyentry = getSaturnNodeKeyInDocument(document,
										"component", "key");

								map.put(keyentry, document);
							} catch (IOException e) {
								e.printStackTrace();
							}

						}
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public Map<String, Document> getMap() {
		return map;
	}

	public void setMap(Map<String, Document> map) {
		this.map = map;
	}
	
	public static String[] getFilePathsFromClasspath(String directory, String suffix) {
		File rootFile = null;
		
		URI classpath = getClasspath();
		
		//如果directory无效,以classpath为根路径
		if (directory == null || directory.trim().equals("")) {
			rootFile = new File(classpath.getPath());
		} else {
			rootFile = new File(classpath.getPath() + System.getProperty("file.separator") + 

directory);
		
			if (!rootFile.exists()) {
				throw new IllegalArgumentException("In classpath: didn't have a directory path is: " + directory);
			}
		}
		
		LinkedList<File> files = new LinkedList<File>();
		files.addLast(rootFile);
		
		List<String> availedFilePath = new LinkedList<String>();
		while (!files.isEmpty()) {
			File file = files.removeFirst();
			
			if (file.isDirectory()) {
				File[] subFiles = file.listFiles();
				for (int i = 0; i < subFiles.length; ++i) {
					files.add(subFiles[i]);
				}
				
				continue;
			}
			
			if (file.getName().endsWith(suffix)) {
				availedFilePath.add(file.getAbsolutePath().replace(System.getProperty

("file.separator"), "/").replace(classpath.getPath().substring(1), ""));
			}
		}
		
		return availedFilePath.toArray(new String[availedFilePath.size()]);
	}
	
	
	
	public static URI getClasspath() {
		URI classpath = null;
		
		try {
			classpath = Thread.currentThread().getContextClassLoader().getResource("").toURI();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		
		return classpath;
	}


	
	public static String getSaturnNodeKeyInDocument(Document document,
			String nodeName, String key) {
		Element rootElement = document.getDocumentElement();
		NodeList componentnodes = rootElement.getElementsByTagName(nodeName);

		for (int i = 0; i < componentnodes.getLength(); i++) {
			Node componentNode = componentnodes.item(i);
			if (componentNode.getNodeType() == Node.ELEMENT_NODE) {
				String key_value = SaturnW3CUtil.getChildNodeValue(
						componentNode, key);
				if (key_value != null && !key_value.equals("")) {
					return key_value;
				}
			}
		}
		return null;

	}
}